'''
Created on 03/09/2009

@author: eh01
'''
from ConfigParser import RawConfigParser
from Queue import Queue
from datastore import database
from datastore.database import DataStore
from datastore.resource import Resource
from runtime import rt
from runtime.spaces import Spaces, SpacesContext
from runtime.task import Task
from spear.a2atask import A2ATask
from spear.pvttask import PVTTask
from spear.wsdl import WSDL
from services.timetask import TimeTask
from spear import pvttask
import logging
import os
import threading
import time
import unittest

LOGGING = logging.WARNING  # logging.DEBUG
                
class PVTTaskTest(unittest.TestCase):

    def setUp(self):
        queue = Queue()
        self.spaces = Spaces()
        spaces_context = SpacesContext(self.spaces, queue)
        runtime = rt.Runtime()
        runtime.initialise_spaces_with_local_config_files(spaces_context)       

        self.temp_database_name = 'test.db'
        self.original_database_name = database.DATABASE_NAME
        database.DATABASE_NAME = self.temp_database_name
        
        section = 'a2a data'
        self.cp = RawConfigParser()
        # the code coverage test does some magic when executing. And the properties_file_path has to be change to use the one below
        # which only just specifies the file name
#        properties_file_path = 'a2a.properties'
        properties_file_path = os.path.dirname(__file__) + '/a2a.properties'
        self.cp.read(properties_file_path)
        self.client_cert_file_name = self.cp.get(section, 'clientcertfilename')
        self.client_cert_password = self.cp.get(section, 'clientcertpassword')
        self.spear_user_username = self.cp.get(section, 'spearuserusername')
        self.spear_user_password = self.cp.get(section, 'spearuserpassword')
        self.spear_user_remote_user = self.cp.get(section, 'spearuserremoteuser')
        self.spear_user_access_level = self.cp.get(section, 'spearuseraccesslevel')
        self.wsdl_path = self.cp.get(section, 'wsdlpath')

    def tearDown(self):
        try:
            os.remove(self.temp_database_name)
        except:
            pass

#    def test_create_lxspearecho_echo_request_data(self):
#        '''[pvttask] test create_lxspearecho_echo_request_data'''
#        access_token = Resource()
#        access_token.spear_user_access_level = 'council'
#        access_token.spear_user_username = 'edwhuy01'
#        access_token.spear_user_password = '123'
#        access_token.spear_user_remote_user = 'edwhuy02'
#        # dummy task def resource
#        task_def_resource = Resource() 
#        task_uri = self.spaces.uri('task:')                       
#        pvt_task = PVTTask(self.spaces, task_uri.eplanning.spear.pvttask, task_def_resource)
#        request = pvt_task.create_lxspearecho_echo_request_data('uat', access_token)
#        self.assertEqual(request.data.echo[1].input, PVTTask.ECHO_TEXT)
#        self.assertEqual(request.data.echo[0].accessToken[0].accessLevel, 'council')
#        self.assertEqual(request.data.echo[0].accessToken[1].hostId, 'edwhuy01')
#        self.assertEqual(request.data.echo[0].accessToken[2].hostPassword, '123')
#        self.assertEqual(request.data.echo[0].accessToken[3].remoteUser, 'edwhuy02')
#
#    def test_create_lxspeardocumenttypes_getall_request_data(self):
#        '''[pvttask] test create_lxspeardocumenttypes_getall_request_data'''
#        access_token = Resource()
#        access_token.spear_user_access_level = 'council'
#        access_token.spear_user_username = 'edwhuy01'
#        access_token.spear_user_password = '123'
#        access_token.spear_user_remote_user = 'edwhuy02'
#        # dummy task def resource
#        task_def_resource = Resource() 
#        task_uri = self.spaces.uri('task:')                       
#        pvt_task = PVTTask(self.spaces, task_uri.eplanning.spear.pvttask, task_def_resource)
#        request = pvt_task.create_lxspeardocumenttypes_getall_request_data('uat', access_token)
#        self.assertEqual(request.data.getAll[0].accessToken[0].accessLevel, 'council')
#        self.assertEqual(request.data.getAll[0].accessToken[1].hostId, 'edwhuy01')
#        self.assertEqual(request.data.getAll[0].accessToken[2].hostPassword, '123')
#        self.assertEqual(request.data.getAll[0].accessToken[3].remoteUser, 'edwhuy02')
#                
#    def test_create_lxapplicationlist_getall_request_data(self):
#        '''[pvttask] test create_lxapplicationlist_getall_request_data'''
#        access_token = Resource()
#        access_token.spear_user_access_level = 'council'
#        access_token.spear_user_username = 'edwhuy01'
#        access_token.spear_user_password = '123'
#        access_token.spear_user_remote_user = 'edwhuy02'
#        # dummy task def resource
#        task_def_resource = Resource() 
#        task_uri = self.spaces.uri('task:')                       
#        pvt_task = PVTTask(self.spaces, task_uri.eplanning.spear.pvttask, task_def_resource)
#        request = pvt_task.create_lxapplicationlist_getall_request_data('uat', access_token)
#        self.assertEqual(request.data.getAll[0].accessToken[0].accessLevel, 'council')
#        self.assertEqual(request.data.getAll[0].accessToken[1].hostId, 'edwhuy01')
#        self.assertEqual(request.data.getAll[0].accessToken[2].hostPassword, '123')
#        self.assertEqual(request.data.getAll[0].accessToken[3].remoteUser, 'edwhuy02')            

    def test_cb_issue_pvt_request_end_to_end_case_1(self):
        '''[pvttask] cb_issue_pvt_request_end_to_end'''
        uri_tasks = self.spaces.uri('tasks:')
        uri_spear = self.spaces.uri('spear:')
        uri_datastore = self.spaces.uri('datastore:')
        uri_pvt = self.spaces.uri('pvt:')
        self.spaces.load_bindings({'task':'http://task.com/'})  
        content_as_string = open(self.client_cert_file_name, 'rb').read()
        client_cert = Resource()
        client_cert.content = content_as_string
        client_cert.set_metadata(uri_datastore.resource.type, uri_spear.type.client_cert)
        client_cert.set_metadata(uri_spear.cert.password, self.client_cert_password)      
        access_token = Resource()
        access_token.spear_user_access_level = self.spear_user_access_level
        access_token.spear_user_username = self.spear_user_username
        access_token.spear_user_password = self.spear_user_password
        access_token.spear_user_remote_user = self.spear_user_remote_user
        access_token.set_metadata(uri_datastore.resource.type, uri_spear.type.pvtaccesstoken)
        rs_wsdl_lxspear_documenttypes = self.create_wsdl_resource('LxSpearDocumentTypes', uri_datastore, uri_spear)
        rs_wsdl_lxspear_echo = self.create_wsdl_resource('LxSpearEcho', uri_datastore, uri_spear)
        rs_wsdl_lxspear_applicationlist = self.create_wsdl_resource('LxSpearApplicationList', uri_datastore, uri_spear)
        # lock is used to indicate when all the calls between tasks are complete
        # notice in task_1 callback method that it releases the lock
        # as this is the last call in the chain of calls between the tasks
        lock = threading.Lock()
        lock.acquire()                
        ds = DataStore()
        ds.put([rs_wsdl_lxspear_documenttypes, rs_wsdl_lxspear_echo, rs_wsdl_lxspear_applicationlist, client_cert, access_token])
        
        # stores the result of the pvt call
        pvt_result = Resource()
                    
        def method_1(method, uri, res, result, context, **kwargs):
            response = context.get(uri_pvt.uat)
            pvt_result.response = response
            lock.release()

        # dummy task def resource
        task_def_resource = Resource()  
        
        dummy_task = Task(self.spaces, uri_tasks.a, task_def_resource)
        dummy_task.method_1 = method_1      
        a2a_task = A2ATask(self.spaces, uri_tasks.eplanning.spear.a2atask, task_def_resource)
        pvt_task = PVTTask(self.spaces, uri_tasks.eplanning.spear.pvttask, task_def_resource)
        time_task = TimeTask(self.spaces, uri_tasks.eplanning.spear.timetask, task_def_resource)
        a2a_task.log_level(LOGGING)         
        a2a_task.start()        
        pvt_task.start()
        time_task.start()
        dummy_task.start()
        dummy_task.queue.put(('method_1', 'get', uri_pvt.uat, None, None, None, {}))
        lock.acquire()
        lock.release()
        a2a_task.task_stop()
        pvt_task.task_stop()
        time_task.task_stop()
        dummy_task.task_stop()
        
        self.assertEqual(pvt_result.response.echo, 'Hello, World')
        # assert the list is not empty
        self.assertTrue(pvt_result.response.documenttypes)
        # assert the list is empty not empty
        self.assertTrue(pvt_result.response.applicationlist)
  
    def test_cb_issue_pvt_request_end_to_end_case_2(self):
        '''[pvttask] cb_issue_pvt_request end to end with timeout exception'''
        uri_tasks = self.spaces.uri('tasks:')
        uri_spear = self.spaces.uri('spear:')
        uri_datastore = self.spaces.uri('datastore:')
        uri_pvt = self.spaces.uri('pvt:')
        self.spaces.load_bindings({'task':'http://task.com/'})  
        content_as_string = open(self.client_cert_file_name, 'rb').read()
        client_cert = Resource()
        client_cert.content = content_as_string
        client_cert.set_metadata(uri_datastore.resource.type, uri_spear.type.client_cert)
        client_cert.set_metadata(uri_spear.cert.password, self.client_cert_password)      
        access_token = Resource()
        access_token.spear_user_access_level = self.spear_user_access_level
        access_token.spear_user_username = self.spear_user_username
        access_token.spear_user_password = self.spear_user_password
        access_token.spear_user_remote_user = self.spear_user_remote_user
        access_token.set_metadata(uri_datastore.resource.type, uri_spear.type.pvtaccesstoken)
        rs_wsdl_lxspear_documenttypes = self.create_wsdl_resource('LxSpearDocumentTypes', uri_datastore, uri_spear)
        rs_wsdl_lxspear_echo = self.create_wsdl_resource('LxSpearEcho', uri_datastore, uri_spear)
        rs_wsdl_lxspear_applicationlist = self.create_wsdl_resource('LxSpearApplicationList', uri_datastore, uri_spear)
        # lock is used to indicate when all the calls between tasks are complete
        # notice in task_1 callback method that it releases the lock
        # as this is the last call in the chain of calls between the tasks
        lock = threading.Lock()
        lock.acquire()                
        ds = DataStore()
        ds.put([rs_wsdl_lxspear_documenttypes, rs_wsdl_lxspear_echo, rs_wsdl_lxspear_applicationlist, client_cert, access_token])
        
        # stores the result of the pvt call
        pvt_result = Resource()
                    
        def method_1(method, uri, res, result, context, **kwargs):
            response = context.get(uri_pvt.uat)
            pvt_result.response = response
            lock.release()

        # dummy task def resource
        task_def_resource = Resource()  
        
        
        # change the default timeout
        default_timeout = pvttask.DEFAULT_TIMEOUT
        pvttask.DEFAULT_TIMEOUT = 2
        
        dummy_task = Task(self.spaces, uri_tasks.a, task_def_resource)
        dummy_task.method_1 = method_1      
        a2a_task = A2ATask(self.spaces, uri_tasks.eplanning.spear.a2atask, task_def_resource)
        pvt_task = PVTTask(self.spaces, uri_tasks.eplanning.spear.pvttask, task_def_resource)
        time_task = TimeTask(self.spaces, uri_tasks.eplanning.spear.timetask, task_def_resource)
        a2a_task.log_level(LOGGING)         
        a2a_task.start()        
        pvt_task.start()
        time_task.start()
        dummy_task.start()
        dummy_task.queue.put(('method_1', 'get', uri_pvt.uat, None, None, None, {}))
        lock.acquire()
        lock.release()
        a2a_task.task_stop()
        pvt_task.task_stop()
        time_task.task_stop()
        dummy_task.task_stop()
        
        # restore the default timeout
        pvttask.DEFAULT_TIMEOUT = default_timeout
        
        self.assertEqual(pvt_result.response.timeout, 'Request to SPEAR Timed Out')
    
    def create_wsdl_resource(self, wsdl_name, uri_datastore, uri_spear):
        wsdl_file = open(self.wsdl_path + wsdl_name +'.wsdl', 'rb')
        wsdl_string = wsdl_file.read()
        wsdl = WSDL(wsdl_string)
        rs_wsdl = Resource()
        rs_wsdl.element_dictionary = wsdl.element_dictionary
        rs_wsdl.set_metadata(uri_datastore.resource.type, uri_spear.type.wsdl)
        rs_wsdl.set_metadata(uri_spear.wsdl.name, wsdl_name)
        return rs_wsdl  
                
if __name__ == "__main__":
    #import sys;sys.argv = ['', 'Test.testName']
    unittest.main()